﻿using System;
using System.Collections.Generic;
using System.Threading;
using Co9320.NamaAlert.Server.Parameters;
using Co9320.NamaAlert.Shared;

namespace Co9320.NamaAlert.Server.BackEnd
{
	/// <summary>
	/// プロセスディスパッチャ
	/// </summary>
	internal static class ProcessDispatcher
	{
		private const int Delay = 100;

		private static Semaphore GetGate = new Semaphore(Properties.Settings.Default.GetMaxProcessing, Properties.Settings.Default.GetMaxProcessing);
		private static ProcessQueue Queue = new ProcessQueue((uint)Properties.Settings.Default.RecursiveLimit);
		private static TokenProcessor TokenInspector = new TokenProcessor(Properties.Settings.Default.ApplicationID, Properties.Settings.Default.KeySeed);
		private static string ConnStr = Properties.Settings.Default.ConnectionStrings;

		public static void Add(AuthorizationTokenParameter Token, IList<AddDeleteParamerter> Values)
		{

			if (!InspectToken(Token))
			{
				return;
			}

			foreach (var element in Values)
			{
				try
				{
					Queue.EnqueueProcess(new AddProcess(element));
				}
				catch (ArgumentException)
				{
					continue;
				}

				ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMain));
			}


		}

		public static void Modify(AuthorizationTokenParameter Token, IList<ModifyParameter> Values)
		{

			if (!InspectToken(Token))
			{

				return;
			}

			foreach (var element in Values)
			{
				try
				{
					Queue.EnqueueProcess(new ModifyProcess(element));
				}
				catch(ArgumentException)
				{
					continue;
				}

				ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMain));
			}

		}

		public static void Delete(AuthorizationTokenParameter Token, IList<AddDeleteParamerter> Values)
		{

			if (!InspectToken(Token))
			{
				return;
			}

			foreach (var element in Values)
			{
				try
				{

					Queue.EnqueueProcess(new DeleteProcess(element));
				}
				catch (ArgumentException)
				{
					continue;
				}

				ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMain));
			}
		}

		private static void ThreadMain(object State)
		{

			ProcessObject Proc = null;

			Proc = Queue.DequeueProcess();

			if(object.ReferenceEquals(Proc,ProcessObject.NoProcessableObject))
			{
				System.Threading.Thread.Sleep(Delay);
				ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMain));
			}
			else if (Proc == null)
			{
				return;
			}
			else
			{
				Proc.DoProcess();
				Queue.ReleaseLock(Proc);
			}
		}

		public static GetReturn Get(AuthorizationTokenParameter Token, IList<GetParameter> Values)
		{
			GetReturn Ret = new GetReturn();
			if (!InspectToken(Token))
			{
				Ret.Delay = int.MaxValue;
				return Ret;
			}

			GetGate.WaitOne();

			GetProcess proc = new GetProcess(Values);
			var result = proc.GetInformation();

			Ret.TagInformations =(List<TagInformation>) result;

			GetGate.Release();

			return Ret;
		}

		private static bool InspectToken(AuthorizationTokenParameter Token)
		{
			if (Token == null)
			{
				return false;
			}

			if (Token.AppricationId == null || Token.HashValue == null)
			{
				return false;
			}

			return TokenInspector.Inspect(Token.Time, Token.HashValue);
		}
	}
}
